package com.example.oauth2.controller;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.oauth2.domain.JiuBoDouTokenService;
import com.example.oauth2.domain.JiuBoDouUserDetails;
import com.example.oauth2.domain.JiuBoDouUsernamePasswordAuthenticationToken;
import com.example.oauth2.generator.domain.UserTable;
import com.example.oauth2.generator.mapper.UserTableMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.TokenRequest;
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * @ClassName Oauth2Controller
 * @Description
 * @Author huyingliang
 * @Date 2024-02-22 15:21
 */
@RestController
@RequestMapping("/oauth2")
public class Oauth2Controller {


    @Autowired
    private TokenEndpoint tokenEndpoint;

    @Autowired
    private RedisTokenStore redisTokenStore;

    @Autowired
    private UserTableMapper userTableMapper;

    @Autowired
    private JiuBoDouTokenService jiuBoDouTokenService;

    @GetMapping("/login/{username}/{password}")
    public String login(@PathVariable("username") String username, @PathVariable("password") String password) throws HttpRequestMethodNotSupportedException {
        Map<String, String> map = new HashMap<>();
        map.put("client_id", "jiubodou_client_id");
        map.put("grant_type", "jiubodou_grant_type");
        map.put("username", username);
        map.put("password", password);

        JiuBoDouUsernamePasswordAuthenticationToken authenticationToken =
                new JiuBoDouUsernamePasswordAuthenticationToken(username, password,
                        new ArrayList<SimpleGrantedAuthority>());
        ResponseEntity<OAuth2AccessToken> postedAccessToken = tokenEndpoint.postAccessToken(authenticationToken,
                map);

        return Objects.requireNonNull(postedAccessToken.getBody()).getValue();
    }

    @GetMapping("/do/{token}")
    public String doTest(@PathVariable("token") String token) {
        OAuth2AccessToken oAuth2AccessToken = redisTokenStore.readAccessToken(token);
        if (oAuth2AccessToken == null) {
            return "token 不存在,请登录";
        }
        Map<String, Object> additionalInformation = oAuth2AccessToken.getAdditionalInformation();
        JiuBoDouUserDetails userDetails = (JiuBoDouUserDetails) additionalInformation.getOrDefault("principal", null);
        String username = userDetails.getUsername();//用户的唯一标识
        Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();//用户有的权限

        /*token 续命  上述操作能获取到用户的 唯一标识和 权限，但是token续命做不到，这里做一下续命*/
        /*如果当前用户的token的剩余时间不足xxxx，那么就换个新的token给他  默认是12小时有效期，也就是43200秒，至于多久换一次token自定*/
        if (oAuth2AccessToken.getExpiresIn() < 43100) {
            OAuth2AccessToken oAuth2AccessToken1 =
                    jiuBoDouTokenService.refreshAccessToken(oAuth2AccessToken.getRefreshToken().getValue()
                            , new TokenRequest(
                                    null,
                                    "jiubodou_client_id",
                                    List.of("all"),
                                    null
                            ));
            return JSON.toJSONString(oAuth2AccessToken1);
        }

        return JSON.toJSONString(oAuth2AccessToken);
        //        可以看出信息系很多，但是我们常用的就是那么几个
//        1. 用户的唯一标识
//        2. 用户的权限
//        {
//            "additionalInformation": {
//            "principal": {
//                "accountNonExpired": true,
//                        "accountNonLocked": true,
//                        "authorities": [
//                {
//                    "authority": "admin"
//                }
//            ],
//                "credentialsNonExpired": true,
//                        "enabled": true,
//                        "password": "$2a$10$erSc3fFkXCHf3ZQmY027ROeiztKa76gknGS1NsXqKjfN5ixrGJ0di",
//                        "username": "17605187513"
//            },
//            "userAuthentication": {
//                "authenticated": true,
//                        "authorities": [
//                {
//                    "authority": "admin"
//                }
//            ],
//                "details": {
//                    "grant_type": "jiubodou_grant_type",
//                            "client_id": "jiubodou_client_id",
//                            "username": "17605187513"
//                },
//                "name": "jiubodou_client_id",
//                        "principal": {
//                    "accountNonExpired": true,
//                            "accountNonLocked": true,
//                            "authorities": [
//                    {
//                        "authority": "admin"
//                    }
//                ],
//                    "credentialsNonExpired": true,
//                            "enabled": true,
//                            "password": "$2a$10$erSc3fFkXCHf3ZQmY027ROeiztKa76gknGS1NsXqKjfN5ixrGJ0di",
//                            "username": "17605187513"
//                }
//            }
//        },
//            "expiration": "2024-03-07 03:33:00.745",
//                "expired": false,
//                "expiresIn": 42971,
//                "refreshToken": {
//            "expiration": "2024-04-05 15:32:53.892",
//                    "value": "8b9492ba-0f4c-4945-9623-3633c7e865ee"
//        },
//            "scope": [
//            "all"
//    ],
//            "tokenType": "bearer",
//                "value": "da7bc74a-4ab9-423e-97ee-ac7bde351e8b"
//        }

    }

    @GetMapping("/findUser/{userMobile}")
    public String findUser(@PathVariable("userMobile") String userMobile) {
        LambdaQueryWrapper<UserTable> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserTable::getUserMobile, userMobile);
        UserTable userTable = userTableMapper.selectOne(queryWrapper);
        return userTable.toString();
    }

    @GetMapping("/register/{userMobile}/{password}")
    public String findUser(@PathVariable("userMobile") String userMobile, @PathVariable("password") String password) {
        UserTable userTable = new UserTable();
        userTable.setUserMobile(userMobile);
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        userTable.setUserPassword(bCryptPasswordEncoder.encode(password));
        userTableMapper.insert(userTable);
        return "register success";
    }


}
